package com.ld.security.shop.crawler.modules.wo.service.impl;

import com.ld.security.common.core.exception.ApiException;
import com.ld.security.common.core.util.JsonUtil;
import com.ld.security.common.core.util.StringUtil;
import com.ld.security.common.core.util.TemplateUtil;
import com.ld.security.common.core.util.UuidUtil;
import com.ld.security.common.mybatis.constant.SqlCondition;
import com.ld.security.common.mybatis.core.wrapper.EntityWrapper;
import com.ld.security.shop.crawler.modules.wo.constant.WoGroupConstant;
import com.ld.security.shop.crawler.modules.wo.constant.WoTaskConstant;
import com.ld.security.shop.crawler.modules.wo.entity.*;
import com.ld.security.shop.crawler.modules.wo.mapping.IWoParseMapping;
import com.ld.security.shop.crawler.modules.wo.service.*;
import com.ld.security.common.mybatis.base.service.*;
import lombok.SneakyThrows;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Transactional
class WoParseServiceImpl extends ISuperServiceImpl<WoParse> implements
        IWoParseService {

    @Autowired
    IWoParseMapping iWoParseMapping;

    @Autowired
    IWoDataService iWoDataService;

    @Autowired
    IWoRuleService iWoRuleService;

    @Autowired
    IWoFileService iWoFileService;

    @Autowired
    IWoTaskService iWoTaskService;

    @Autowired
    IWoGroupService iWoGroupService;

    /**
     *
     * @param root
     * @param woRuleList 解析规则
     * @return
     */
    public Map parse(WoTask content,Element root,List<WoRule> woRuleList) {
        HashMap map = new HashMap<>();

        for (WoRule woRule : woRuleList) {
            Elements es =  root.select(woRule.getContent());
            Object val = null;
            WoGroup pageGroup = null;
            WoGroup detailsGroup = null;
            for (Element element :es) {
                switch ( woRule.getRuleType()){
                    case text:{
                       val =  element.text();
                        break;
                    }
                    case html:{
                        val=element.outerHtml();
                        break;
                    }
                    case attr:{
                        val=element.attr(woRule.getAttrName());
                        break;
                    }
                    case tree_parse:{
                        if(woRule.getChildren() != null){
                            val = parse(content,element,woRule.getChildren());
                        }else{
                            ApiException.throw400("缺少子规则");
                        }
                        break;
                    }
                    case new_task:{
                        String url = element.attr(woRule.getAttrName());
                        if(content.getOpenTask()){
                            WoTask woTask =  iWoTaskService.newInstance();
                            woTask.setStatus(WoTaskConstant.status.await);
                            woTask.setOpenTask(false);
                            woTask.setUrl(url);
                            woTask.setLabel(content.getMapJson().get("groupId").toString()+":"+url);
                            iWoTaskService.parseSave(woTask);
                        }
                        val = url;
                        break;
                    }
                    case down_file:{
                        String url = element.attr(woRule.getAttrName());
                        iWoFileService.downFile(content,url);
                        val = url;
                        break;
                    }
                    case new_details:{
                        String url = element.attr(woRule.getAttrName());
                        if(detailsGroup == null){
                            detailsGroup = new WoGroup();

                            detailsGroup.setStatus(WoGroupConstant.status.setout);
                            detailsGroup.setUrlType(WoGroupConstant.urlType.details);
                            detailsGroup.setLabel(content.getMapJson().get("groupId").toString());
                        }
                        if(detailsGroup.getContent() == null){
                            detailsGroup.setContent(url);
                        }else{
                            detailsGroup.setContent(detailsGroup.getContent()+","+url);
                        }
                        val = url;
                        break;
                    }
                    case new_page:{
                        String url = element.attr(woRule.getAttrName());
                        if(pageGroup == null){
                            pageGroup = new WoGroup();
                            pageGroup.setStatus(WoGroupConstant.status.setout);
                            pageGroup.setUrlType(WoGroupConstant.urlType.page);
                            pageGroup.setLabel(content.getMapJson().get("groupId").toString());
                        }
                        if(pageGroup.getContent() == null){
                            pageGroup.setContent(url);
                        }else{
                            pageGroup.setContent(pageGroup.getContent()+","+url);
                        }
                        val = url;
                        break;
                    }

                }


                Object vals =  map.get(woRule.getLabel());
                if(vals == null){
                    map.put(woRule.getLabel(),val);
                }else if(val instanceof List){
                    List list = (List) vals;
                    list.add(val);
                } else{
                    LinkedList linkedList =  new LinkedList<>();
                    linkedList.add(val);
                    linkedList.add(vals);
                    map.put(woRule.getLabel(),linkedList);
                }
            }
            if(pageGroup != null){
                iWoGroupService.parseSave(pageGroup);
            }
            if(detailsGroup != null){
                iWoGroupService.parseSave(detailsGroup);
            }
        }
        if(map.keySet().isEmpty()){
            ApiException.throw400("数据解析失败,空数据");
        }
        return map;
    }

    private String newUrl(String rootUrl,String url){
        if(!url.startsWith("http")){
            url = rootUrl+url;
        }
        return url;
    }

    public Map parse(WoTask woTask,List<WoRule> woRuleList) {
        Document document = Jsoup.parse(woTask.getContent());
        String rootUrl="";

        try {
            URL uri =  new URL(woTask.getUrl());
            rootUrl=uri.getProtocol()+"://"+ uri.getAuthority();
        }catch (Exception e){
            ApiException.throw400("异常url:"+woTask.getUrl());
        }
        Elements as =  document.select("a");
        for (Element a : as) {
            String url = a.attr("href");
            url = this.newUrl(rootUrl,url);
            a.attr("href",url);
        }
        Elements imgs =  document.select("img");
        for (Element img : imgs) {
            String url = img.attr("src");
            url = this.newUrl(rootUrl,url);
            img.attr("src",url);
        }
        return parse(woTask,document,woRuleList);
    }


        @Override
    public void parse(WoTask woTask) {

        WoParse woParse =findByMatchUrl(woTask.getUrl());
        List<WoRule> woRuleList =   iWoRuleService.findByParseId(woParse.getId());

        Map map = this.parse(woTask ,woRuleList);

        WoData woData = iWoDataService.newInstance();

        woData.setTaskId(woTask.getId());
        woData.setTaskUrl(woTask.getUrl());
        woData.setContent(JsonUtil.toJson(map));
        iWoDataService.save(woData);
    }

    @Override
    public WoParse findByMatchUrl(String url) {

        List<WoParse> woParses =  this.all();

        for (WoParse woParse : woParses) {

            String content =StringUtil.removeLine(woParse.getContent());

            String[] strs = content.split(",");

            for (String s :strs) {
                if(StringUtil.match(s,url)){
                    return woParse;
                }
            }
        }
        ApiException.throw400("解析对象不存在:"+url);
        return null;
    }
}
